#!/bin/bash

# All tests must pass!
set -o errexit

ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

if [[ ! -f "/lib/sdc/.sdc-test-no-production-data" ]]; then
    cat <<EOF
To run this test you must create the file:

    /lib/sdc/.sdc-test-no-production-data

after ensuring you have no production data on this machine.
EOF
    exit 2
fi

start_time=$(date +%s)

if [[ $(uname -s) != 'SunOS' ]]; then
    echo "FATAL: this can only run on SmartOS"
    exit 1
fi

if [[ $(zonename) != 'global' ]]; then
    echo "FATAL: this can only run in the GZ"
    exit 1
fi

if [[ $(id -u) != 0 ]]; then
    echo "FATAL: this can only run as root"
    exit 1
fi

if [[ -z "$1" ]]; then
    echo "FATAL: no test file specified"
    exit 1
fi

echo "# Running $1"

# Before starting tests, ensure we have the source(s) we want for test VM images

have_sources="imgadm sources | sort"
want_source="grep IMAGES_SOURCE ${ROOT}/common/vmtest.js | cut -d\' -f2"

for src in $(comm -1 -3 <(eval ${have_sources}) <(eval ${want_source})); do
    imgadm sources -a "${src}"
done

# Ensure images used by tests are installed

installed_images='imgadm list -H -o uuid | sort'
want_images="cat ${ROOT}/common/vmtest.js | grep exports\.CURRENT_.*_UUID \
    | grep -v "process.env" | cut -d \"'\" -f2 | sort"

for img in $(comm -1 -3 <(eval ${installed_images}) <(eval ${want_images})); do
    if [[ ${img} == "71101322-43a5-11e1-8f01-cf2a3031a7f4" ]]; then
        MANTA_PATH="https://us-east.manta.joyent.com/Joyent_Dev/public/old_images/ubuntu-10.04"
        (cd /var/tmp && curl -kO ${MANTA_PATH}/${img}.file \
            && curl -kO ${MANTA_PATH}/${img}.manifest \
            && imgadm install -f ${img}.file -m ${img}.manifest \
            && rm -f ${img}.file ${img}.manifest)
    elif [[ ${img} == "01b2c898-945f-11e1-a523-af1afbe22822" ]]; then
        MANTA_PATH="https://us-east.manta.joyent.com/Joyent_Dev/public/old_images/smartos-1.6.3"
        (cd /var/tmp && curl -kO ${MANTA_PATH}/${img}.file \
            && curl -kO ${MANTA_PATH}/${img}.manifest \
            && imgadm install -f ${img}.file -m ${img}.manifest \
            && rm -f ${img}.file ${img}.manifest)
    elif [[ ${img} == "462d1d03-8457-e134-a408-cf9ea2b9be96" ]]; then
        # To be removed by IMAGE-1116
        MANTA_PATH="https://us-east.manta.joyent.com/Joyent_Dev/public/bhyve/images/$img"
        (cd /var/tmp && curl -kO "${MANTA_PATH}/manifest.json" \
            && curl -kO "${MANTA_PATH}/disk0.zfs.gz" \
            && imgadm install -m manifest.json -f disk0.zfs.gz \
            && rm -f manifest.json disk0.zfs.gz)
    else
        imgadm import "${img}"
    fi
done

# Special case for docker

imgadm sources --add-docker-hub
export DOCKER_BASE_IMAGE_UUID=$(imgadm list -o uuid,tags \
    | grep "\"docker:repo\":\"busybox\"" \
    | cut -d' ' -f1 \
    | head -1)
if [[ -z ${DOCKER_BASE_IMAGE_UUID} ]]; then
    imgadm import busybox:1.24.0
    export DOCKER_BASE_IMAGE_UUID=$(imgadm list -o uuid,tags \
        | grep "\"docker:repo\":\"busybox\"" \
        | cut -d' ' -f1)
    if [[ -z ${DOCKER_BASE_IMAGE_UUID} ]]; then
        echo "Unable to download busybox:1.24.0 docker image" >&2
        exit 1
    fi
fi

# Ensure nic tags needed by tests exist

for tag in admin external; do
    if ! /usr/bin/nictagadm exists ${tag} >/dev/null 2>&1; then
        echo "Missing NIC tag: ${tag}, please add w/ nictagadm and try again" >&2
        exit 2
    fi
done

# Ensure the dummy uefi image exists

uefi_img_uuid="45d86edd-8cf4-6c7c-f018-8e27b24c550e"
if ! imgadm info "$uefi_img_uuid" >/dev/null 2>&1; then
	uefi_zvol=zones/${uefi_img_uuid}-tmp
	uefi_snap=${uefi_zvol}@final
	uefi_zfs=/var/tmp/${uefi_img_uuid}.zfs
	uefi_manifest=/var/tmp/${uefi_img_uuid}.imgmanifest

	if zfs list "$uefi_zvol" >/dev/null 2>&1; then
		if ! zfs destroy -r "$uefi_zvol"; then
			echo "Unable to clean up earlier uefi image" >&2
			exit 1
		fi
	fi
	if ! zfs create -V 1g -s "$uefi_zvol"; then
		echo "Unable to create uefi zvol $uefi_zvol" >&2
		exit 1
	fi
	if ! zfs snapshot "$uefi_snap"; then
		echo "Unable to create uefi snapshot $uefi_snap" >&2
		exit 1
	fi
	if ! zfs send "$uefi_snap" >$uefi_zfs; then
		echo "Unable to send uefi snapshot $uefi_snap to $uefi_zfs" >&2
		exit 1
	fi
	uefi_size=$(stat -c %s "$uefi_zfs")
	uefi_sha1=$(digest -a sha1 "$uefi_zfs")
	cat >$uefi_manifest <<-NOMORE
	{
	  "v": 2,
	  "uuid": "$uefi_img_uuid",
	  "name": "uefi-dummy",
	  "version": "1.0",
	  "type": "zvol",
	  "os": "windows",
	  "image_size": 1024,
	  "description": "Dummy uefi image for VM tests",
	  "requirements": {
	    "brand": "bhyve",
	    "bootrom": "uefi"
	  },
	  "files": [
	    {
	      "sha1": "$uefi_sha1",
	      "size": $uefi_size,
	      "compression": "none"
	    }
	  ]
	}
	NOMORE
	if (( $? != 0)); then
		echo "Unable to create uefi manifest $uefi_manifest" >&2
		exit 1
	fi
	if ! imgadm install -m "$uefi_manifest" -f "$uefi_zfs"; then
		echo "Unable to install uefi image from $uefi_manifest and" \
		    "$uefi_zfs" >&2
		exit 1
	fi

	# Clean up temporary stuff, but don't freak out if it fails.
	rm -f "$uefi_manifest" "$uefi_zfs"
	zfs destroy -r "$uefi_zvol"
fi

# Keep track of when we started so it is easy to identify new core files
touch /tmp/runtest.start.$$

set +o errexit
set -o pipefail
/usr/bin/ctrun -l child -o noorphan /usr/node/bin/node \
    --abort_on_uncaught_exception \
    /usr/vm/node_modules/nodeunit/bin/nodeunit \
    --reporter tap $1 | tee -a /tmp/test.output.$$
TEST_EXIT_CODE=$?
set +o pipefail
set -o errexit

end_time=$(date +%s)
elapsed=$((${end_time} - ${start_time}))

tests=$(grep "^# tests [0-9]" /tmp/test.output.$$ | cut -d ' ' -f3 | xargs | tr ' ' '+' | bc)
passed=$(grep "^# pass  [0-9]" /tmp/test.output.$$ | tr -s ' ' | cut -d ' ' -f3 | xargs | tr ' ' '+' | bc)
skipped=$(grep "^# skip  [0-9]" /tmp/test.output.$$ | tr -s ' ' | cut -d ' ' -f3 | xargs | tr ' ' '+' | bc)

[[ -z ${tests} ]] && tests=0
[[ -z ${passed} ]] && passed=0
[[ -z ${skipped} ]] && skipped=0

fail=$((${tests} - ${passed} - ${skipped}))

if [[ ${TEST_EXIT_CODE} != 0 ]]; then
    fail=$((${fail} + 1))
    tests="?"
fi

if [[ -t 0 ]]; then
    # We're on a terminal so output the summary
    echo "#"
    echo "# $1 TEST COMPLETE IN ${elapsed} SECONDS, SUMMARY:"
    echo "#"
    if [[ ${tests} != "?" ]]; then
        echo -e "# \033[32mPASS: ${passed} / ${tests}\033[39m"
    fi
    if [[ ${skipped} -gt 0 ]]; then
        echo -e "# \033[31mSKIP: ${skipped} / ${tests}\033[39m"
    fi
    if [[ ${fail} -gt 0 ]]; then
        echo -e "# \033[31mFAIL: ${fail} / ${tests}\033[39m"
    fi
    echo "#"
fi

coredir=$(cd $(dirname $(coreadm $$ | awk '{gsub("%Z", "/", $2); print $2;}')) \
    && pwd -P)
cores=$(find "$coredir" -type f -newer /tmp/runtest.start.$$)
rm /tmp/runtest.start.$$

if [[ -n "$cores" ]]; then
    if [[ -t 0 ]]; then
        echo -e "# \033[31mNew core files\033[39m"
    fi

    # Send a list of core files to stdout for testers and `runtests` to see
    # and another in this run's log.
    for core in $cores; do
        echo "# new core: $core"
    done | tee -a /tmp/test.output.$$
fi

if [[ ${fail} -gt 0 || -n "$cores" ]]; then
    exit 1
fi

exit 0
